package com.gonsin.ta.logic.parse;

import cn.hutool.core.collection.CollectionUtil;
import com.gonsin.ta.logic.config.BaseTaConfig;
import com.gonsin.ta.logic.enums.NodeTypeEnum;
import com.gonsin.ta.logic.exceptions.TaException;
import com.gonsin.ta.logic.node.TaNodeBuilder;
import com.gonsin.ta.logic.node.groovy.GroovyScriptExecutor;
import com.gonsin.ta.logic.process.SignalCenter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ResourceUtils;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import static com.gonsin.ta.logic.parse.Constant.*;

/**
 * 基于xml的解析器
 */
@Component
@Slf4j
public class TaXmlParse implements ITaParser{

    @Autowired
    private BaseTaConfig config;

    @Autowired
    private TaFileReader fileReader;

    @Autowired
    private SignalCenter signalCenter;

    @Autowired
    private GroovyScriptExecutor groovyScriptExecutor;

    @Override
    public void parse(Set<String> contentList) throws Exception {
        if (CollectionUtil.isEmpty(contentList)) {
            return;
        }
        String path = config.getDefaultTaPath();

        for (String file : contentList) {
            String content = fileReader.readContent(path, file, config.getFileCharset());
            Document document = DocumentHelper.parseText(content);
            ParserHelper.parseDocument(
                    document,
                    element -> parseOneChain(file, element)
            );
        }
    }

    @Override
    public void parseNode(Set<String> contentList) throws Exception {
        // **.ta.xml文件，得到chain列表
        if (CollectionUtil.isEmpty(contentList)) {
            return;
        }
        String path = config.getDefaultTaPath();

        for (String file : contentList) {
            String content = fileReader.readContent(path, file, config.getFileCharset());
            Document document = DocumentHelper.parseText(content);
            ParserHelper.parseNodeDocument(
                    document,
                    element -> parseOneNode(file, element)
            );
        }
    }


    /**
     */
    public void parseOneNode(String filename, Element e){
        String nodeId = e.attributeValue(ID);
        if(StringUtils.isEmpty(nodeId)){
            throw new TaException("<node>标签必须填入id值，请查看{}", filename);
        }
        String nodeType = e.attributeValue(NODE_TYPE);
        NodeTypeEnum type = NodeTypeEnum.getEnumByCode(nodeType);
        if(type == null){
            throw new TaException("<node>标签必须填入nodeType值，且取值为RUN,SWITCH,SIGNAL其中之一，请查看{}", filename);
        }
        String groovy = null;
        String file = e.attributeValue(FILE);
        if(file == null){
            groovy = e.getText();
        } else {
            groovy = readFromFile(file, config.getFileCharset());

        }
        TaNodeBuilder builder = null;
        builder = TaNodeBuilder.createBuilder(groovyScriptExecutor);
        builder.setFilename(filename);
        builder.setNodeId(nodeId);
        builder.setNodeType(type);
        builder.setGroovyScript(groovy).build();
    }

    private String readFromFile(String file, String fileCharset) {

        String originFile = file;
        List<String> searchPaths = new ArrayList<>();
        File groovyFile = new File(file);
        if(groovyFile.exists()){
            try {
                return FileUtils.readFileToString(new File(file), fileCharset);
            } catch (IOException ex) {

            }
        }
        searchPaths.add(new File(file).getAbsolutePath());

        // 如果不是绝对路径
        if(!groovyFile.isAbsolute()){
            file = config.getDefaultTaPath() + file;
            groovyFile = new File(file);
            if(groovyFile.exists()){
                try {
                    return FileUtils.readFileToString(new File(file), fileCharset);
                } catch (IOException ex) {
                    searchPaths.add(new File(file).getAbsolutePath());
                }
            }
        } else {
            throw new TaException("找不到groovy文件位置，已经搜索目录包含{}", searchPaths);
        }

        file = originFile;
        try {
            groovyFile = ResourceUtils.getFile(file);
            return FileUtils.readFileToString(groovyFile, fileCharset);
        } catch (Exception ex) {
            searchPaths.add("classpath:" + file);
        }

        file = config.getDefaultTaPath() + file;
        try {
            groovyFile = ResourceUtils.getFile(file);
            return FileUtils.readFileToString(groovyFile, fileCharset);
        } catch (Exception ex) {
            searchPaths.add("classpath:" + file);
        }

        throw new TaException("找不到groovy文件位置，已经搜索目录包含{}", searchPaths);
    }


    /**
     */
    public void parseOneChain(String filename, Element e){
//        Element e = elementStruct.element;
        String chainId = e.attributeValue(ID);
        String chainName = e.attributeValue(NAME);
        String el = e.getText();
        TaChainBuilder builder = null;
        builder = TaChainBuilder.createChain(signalCenter);
        builder.setFilename(filename);
        if(StringUtils.isNotEmpty(chainName)){
            builder.setChainName(chainName);
        }
        if(StringUtils.isNotEmpty(chainId)){
            builder.setChainId(chainId);
        }
        builder.setQL(el).build();
    }
}
